package main

import (
	"context"
	"fmt"
	"gin-lite/configs"
	"gin-lite/internal/pkg/env"
	"gin-lite/internal/pkg/logger"
	"gin-lite/internal/pkg/shutdown"
	"gin-lite/internal/repository/mysql"
	"gin-lite/internal/repository/mysql/models"
	"gin-lite/internal/repository/redis"
	"gin-lite/internal/router"
	"go.uber.org/zap"
	"net/http"
	"time"
)

func main() {
	cfg := configs.Get()

	// 日志测试 TODO 创建日志对象修改为读取配置文件配置来创建
	accessLogger, err := logger.NewJSONLogger(
		logger.WithDebugLevel(),
		logger.WithTimeLayout(logger.TimeLayoutMil),
		logger.WithFileRotationP(
			cfg.Log.Output.File.Path,
			cfg.Log.Output.File.MaxSize,
			cfg.Log.Output.File.MaxBackups,
			cfg.Log.Output.File.MaxAge,
			cfg.Log.Output.File.Compress),
		logger.WithField("project_name", fmt.Sprintf("%s[%s]", configs.Get().Server.Name, env.Active().Value())),
	)
	if err != nil {
		panic(err)
	}
	defer func() {
		_ = accessLogger.Sync()
	}()

	// mysql
	dbRepo := mysql.New(configs.Get())

	var a models.User
	dbRepo.GetConn().First(&a)
	fmt.Println(a)

	var b models.User
	dbRepo.GetConn("default.read").Where("username = ?", "wyj").First(&b)
	fmt.Println(b)

	var c models.User
	dbRepo.GetConn("blog.write").Where("username = ?", "wm").First(&c)
	fmt.Println(c)

	var d models.User
	dbRepo.GetConn("blog.read").Where("username = ?", "gjy").First(&d)
	fmt.Println(d)

	// redis
	redisClient := redis.New(configs.Get())

	// init http
	mux, err := router.NewHTTPMux(accessLogger, dbRepo, redisClient)
	if err != nil {
		panic(err)
	}

	server := &http.Server{ // TODO server 可以配置更多信息
		Addr:    fmt.Sprintf(":%s", cfg.Server.Port),
		Handler: mux,
	}

	go func() {
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			accessLogger.Fatal("http server startup err", zap.Error(err))
		}
	}()

	shutdown.Close(
		func() {
			// shutdown http server
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()

			if err := server.Shutdown(ctx); err != nil {
				accessLogger.Error("server shutdown err", zap.Error(err))
			}

			select {
			case <-ctx.Done():
			}

			// shutdown redis
			if err := redis.Close(); err != nil {
				accessLogger.Error("redis shutdown err", zap.Error(err))
			}

			// shutdown db
			if err := dbRepo.Close(configs.Get()); err != nil {
				accessLogger.Error("db shutdown err", zap.Error(err))
			}

			accessLogger.Info("server graceful shutdown success")
		},
	)
}
